/**********************************************************************************************************
** 程序文件：	AES.h
** 程序版本：	2.0
** 开发环境：	RealView MDK-ARM 5.17
** 作者:		盖书永
** 生成日期:	2015年12月6日16:08:42
** 文件功能：	AES 加密解密功能

AES分组加密简介
1、首先应该明白AES是基于数据块的加密方式，也就是说，每次处理的数据是一块（16字节），当数据不是16字节的倍数
   时填充，这就是所谓的分组密码（区别于基于比特位的流密码），16字节是分组长度。
2、分组加密方式：
ECB模式（电子密码本）：
	一个明文数据块加密成一个密文数据块，下一个明文数据块加密成下一个密文数据块；这种加密比较简单，而且，如
	果存在相同的密文数据块就很容易推断出使用了ECB加密，这样破解者就只用解密部分密文，而不必解密整个密文。
    优点:   1.简单；   2.有利于并行计算；  3.误差不会被扩散； 因此，此模式适于加密小消息。
    缺点:   1.不能隐藏明文的模式；  2.可能对明文进行主动攻击； 
CBC模式（密码分组链接）：
	使用一个初始化向量与第一组明文进行异或操作，然后进行加密，然后再将密文作为向量与下一组明文进行异或操作。
	这样保证了每组密文依赖它前面的所有明文。
    优点：  不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。 
    缺点：  1.不利于并行计算；  2.误差传递；  3.需要初始化向量IV 
3、注意，填充方式为：PKCS7Padding
**********************************************************************************************************/
#ifndef _AES_H_
#define _AES_H_

typedef enum {
	AES128 = 128,				//AES 128位加密
	AES192 = 192,				//AES 192位加密
	AES256 = 256				//AES 256位加密
} AES_KEYLEN;					//AES秘钥长度

typedef enum {
	AES_ECB_DECRYPT,			//AES ECB模式解密	
	AES_ECB_ENCRYPT,			//AES ECB模式加密
	AES_CBC_DECRYPT,			//AES CBC模式解密	
	AES_CBC_ENCRYPT				//AES CBC模式加密	
} AES_MODE;						//AES工作模式

typedef enum {
	AES_OK			= 0,		//成功
	INVALID_KEY		= -1,		//无效秘钥
	INVALID_KEY_LEN	= -2,		//无效秘钥长度
	INVALID_KEY_IV	= -3,		//无效秘钥向量
	INVALID_MODE	= -4,		//无效工作模式 
	INVALID_CIPHER_TEXT	= -5	//无效密文
} AES_ERR;						//AES错误原因

typedef struct
{
	AES_MODE	  mode;			//AES工作模式	
	unsigned char iv[16];		//密钥偏移量	
	unsigned int  nr;			//AES轮数
	unsigned int  *rk;			//AES轮密钥
	unsigned int  buf[68];      //缓存
	unsigned char temp1[16]; 	//临时缓存1
	unsigned char temp2[16]; 	//临时缓存2	
	unsigned int  size;			//记录未16字节对齐的缓存字节数
}AES_CTX;

#define AES_Warn(a) 			Log_Error(a)//警告输出	

/**********************************************************************************************************
* 函数名称： AES_ERR AES_Init(AES_CTX *ctx, AES_MODE mode, AES_KEYLEN keylen, char *key, char *iv)
* 函数说明： AES 加密和解密模块初始化
* 输入参数： 结构体指针，工作模式，秘钥长度，秘钥，秘钥向量（工作模式为AES_ECB_DECRYPT和AES_ECB_ENCRYPT时，此参数iv设为NULL）
* 返回参数： AES_OK：成功，INVALID_KEY：秘钥无效，INVALID_KEY_LEN：秘钥长度无效，INVALID_KEY_IV：秘钥向量无效，INVALID_MODE：无效的工作模式
**********************************************************************************************************/
AES_ERR AES_Init(AES_CTX *ctx, AES_MODE mode, AES_KEYLEN keylen, char *key, char *iv);

/**********************************************************************************************************
* 函数名称： int AES_Update( AES_CTX *ctx, char *in, unsigned int inlen, char *out )
* 函数说明： AES数据加密解密处理，可进行数据流加密解密
* 输入参数： 结构体指针，输入数据缓存区指针，输入数据长度，输出数据缓存区指针
* 返回参数： 返回输出数据长度
**********************************************************************************************************/
int AES_Update(AES_CTX *ctx, char *in, unsigned int inlen, char *out);

/**********************************************************************************************************
* 函数名称： int AES_Final( AES_CTX *ctx, char *out, AES_ERR *err)
* 函数说明： AES 执行PKCS7Padding填充块和去除填充块，放在最后调用
* 输入参数： 输入数据缓存区指针，输出数据缓存区指针，状态反馈值
* 返回参数： 返回输出数据长度
**********************************************************************************************************/
int AES_Final(AES_CTX *ctx, char *out, AES_ERR *err);

/**********************************************************************************************************
* 函数名称： int AES_ECB_Encrypt(AES_KEYLEN keylen, char *key, char *in, unsigned int inlen, char *out)
* 函数说明： 一段固定数据块进行AES ECB模式加密。(适用于固定数据块)
* 输入参数： 加密位数，秘钥，输入数据缓存区指针，输入数据长度，输出数据缓存区指针
* 返回参数： 返回输出加密后的数据长度，返回-1：秘钥无效，-2：秘钥长度无效，-3：秘钥向量无效
**********************************************************************************************************/
int AES_ECB_Encrypt(AES_KEYLEN keylen, char *key, char *in, unsigned int inlen, char *out);

/**********************************************************************************************************
* 函数名称： int AES_ECB_Decrypt(AES_KEYLEN keylen, char *key, char *in, unsigned int inlen, char *out)
* 函数说明： 一段固定的加密数据块进行AES ECB模式解密。(适用于固定数据块)
* 输入参数： 加密位数，秘钥，输入数据缓存区指针，输入数据长度，输出数据缓存区指针
* 返回参数： 返回输出加密后的数据长度，返回-1：秘钥无效，-2：秘钥长度无效，-3：秘钥向量无效
**********************************************************************************************************/
int AES_ECB_Decrypt(AES_KEYLEN keylen, char *key, char *in, unsigned int inlen, char *out);

/**********************************************************************************************************
* 函数名称： int AES_CBC_Encrypt(AES_KEYLEN keylen, char *key, char *iv, char *in, unsigned int inlen, char *out)
* 函数说明： 一段固定数据块进行AES CBC模式加密。(适用于固定数据块)
* 输入参数： 输入数据缓存区指针，输入数据长度，输出数据缓存区指针
* 返回参数： 返回输出加密后的数据长度，返回-1：秘钥无效，-2：秘钥长度无效，-3：秘钥向量无效
**********************************************************************************************************/
int AES_CBC_Encrypt(AES_KEYLEN keylen, char *key, char *iv, char *in, unsigned int inlen, char *out);
/**********************************************************************************************************
* 函数名称： int AES_CBC_Decrypt(AES_KEYLEN keylen, char *key, char *iv, char *in, unsigned int inlen, char *out)
* 函数说明： 一段固定的加密数据块进行AES CBC模式解密。(适用于固定数据块)
* 输入参数： 输入数据缓存区指针，输入数据长度，输出数据缓存区指针（输出缓存区长度至少为输入数据长度）
* 返回参数： 返回输出加密后的数据长度，返回-1：秘钥无效，-2：秘钥长度无效，-3：秘钥向量无效
**********************************************************************************************************/
int AES_CBC_Decrypt(AES_KEYLEN keylen, char *key, char *iv, char *in, unsigned int inlen, char *out);

#endif


